import { ExecutionContext } from "@nestjs/common";

/**
 * 从请求上下文中获取请求对象
 *
 * @param {ExecutionContext} context 请求上下文
 * @returns {any} 请求对象
 */
export const getReqFromContext = (context: ExecutionContext): any => {
  return context.switchToHttp().getRequest();
}

/**
 * 从请求上下文中获取请求头
 *
 * @param {ExecutionContext} context 请求上下文
 * @returns {HeadersInit} 请求头
 */
export const getReqHeadersFromContext = (context: ExecutionContext): HeadersInit => {
  return getReqFromContext(context).headers;
};

/**
 * 通过请求上下文修改请求头
 *
 * @param {ExecutionContext} context 请求上下文
 * @param {string} headerKey 请求头的键
 * @param {string} headerValue 请求头的值
 */
export const modifyReqHeadersByContext = (context: ExecutionContext, headerKey: string, headerValue: string) => {
  const reqHeaders = getReqHeadersFromContext(context);
  reqHeaders[headerKey] = headerValue;
};

/**
 * 从请求上下文中获取的请求体的类型
 */
export type ReqBody =
  ReadableStream<any>
  | Blob
  | ArrayBufferView<ArrayBufferLike>
  | ArrayBuffer
  | FormData
  | URLSearchParams
  | string;

/**
 * 从请求上下文中获取请求体
 *
 * @param {ExecutionContext} context 请求上下文
 * @returns {ReqBody} 请求体
 */
export const getReqBodyFromContext = (context: ExecutionContext): ReqBody => {
  return getReqFromContext(context).body;
};

/**
 * 从请求上下文中获取请求方法
 *
 * @param {ExecutionContext} context 请求上下文
 * @returns {string} 请求方法
 */
export const getReqMethodFromContext = (context: ExecutionContext): string => {
  return getReqFromContext(context).method;
};

/**
 * 从请求对象中获取请求参数
 *
 * @param req 请求对象
 * @returns {any} 请求参数
 */
export const getReqDataFromReq = (req: any) => {
  if (req.method === "GET") {
    return req.query;
  } else {
    return req.body;
  }
}

/**
 * 从请求上下文中获取请求数据
 *
 * @param {ExecutionContext} context 请求上下文
 * @returns {any} 请求数据
 */
export const getReqDataFromContext = (context: ExecutionContext): any => {
  const req = getReqFromContext(context);
  return getReqDataFromReq(req);
};

/**
 * 修改请求上下文中的请求体
 *
 * @param {ExecutionContext} context 请求上下文
 * @param body 新的请求体
 */
export const modifyReqBodyByContext = (context: ExecutionContext, body: any) => {
  getReqFromContext(context).body = body;
};

/**
 * 设置请求对象中的请求参数
 *
 * @param req 请求对象
 * @param data 请求参数
 */
export const setReqData = (req: any, data: any) => {
  if (req.method === "GET") {
    req.query = data;
  } else {
    req.body = data;
  }
}